package com.mylock;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.util.Collections;
import java.util.List;

/**
 * @author:wesley
 */
public class MyDistributedLock {

    private String selftPath = "";

    private String waitPath = "";

    private ZooKeeper zk;


    private String groupPath = "/disGroup";

    private String groupSubPath = "/disGroup/sub";


    private String log_prefix = Thread.currentThread().getName();


    private MyLockWatch myLockWatch;

    public MyDistributedLock(ZooKeeper zk) {
        this.zk = zk;
    }

    public MyLockWatch getMyLockWatch() {
        return myLockWatch;
    }

    public void setMyLockWatch(MyLockWatch myLockWatch) {
        this.myLockWatch = myLockWatch;
    }


    public String getSelftPath() {
        return selftPath;
    }

    public void setSelftPath(String selftPath) {
        this.selftPath = selftPath;
    }

    public String getWaitPath() {
        return waitPath;
    }


    public boolean isMinPath() throws KeeperException, InterruptedException {

        //所有子节点
        List<String> childrenNodes = zk.getChildren(groupPath, false);;

        //排序
        Collections.sort(childrenNodes);

        //获取索引
        int index = childrenNodes.indexOf(selftPath.substring(groupPath.length() + 1));

        if (index < 0) {
            //根本不存在
            System.out.println(log_prefix +"节点不存在。。。。");
            return false;

        } else if (index == 0) {
            //排在首位
            System.out.println(log_prefix+ "我排在第一个。。。");
            return true;
        } else {
            //递归调用了。。。。排队
            this.waitPath = groupPath + "/" +childrenNodes.get(index - 1);
            try {
                zk.getData(waitPath, myLockWatch, new Stat());
                return false;
            } catch (KeeperException e) {
                if (zk.exists(waitPath , false) == null) {
                    System.out.println(log_prefix + "不存在..");
                    return isMinPath();
                } else {
                    throw e;
                }
            }
        }
    }


    /**
     * 获取锁的时候直接创建一个路径，判断是否是最小的
     *
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public boolean getLock() throws KeeperException, InterruptedException {
        selftPath = zk.create(groupSubPath , null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(log_prefix+"创建的节点 --- > " + selftPath);
        if (isMinPath()) {
            return true;
        }
        return false;
    }


    public void unLock() throws KeeperException, InterruptedException {
        if (zk.exists(selftPath, false) == null){
            System.out.println(log_prefix + "节点已经不存在....");
            return;
        } else {
            System.out.println(log_prefix + "做完了，释放锁...."+selftPath);
            zk.delete(selftPath , -1);
            zk.close();
        }
    }


    public synchronized void createRootNode() throws KeeperException, InterruptedException {
        if(zk.exists(groupPath, false) == null){
            String data = log_prefix+" created "+groupPath+" node ";
            zk.create(groupPath, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        } else {
            System.out.println("root 节点已经存在，不需要创建了");
        }
    }

}
